package com.buli.blmall.generator.metadata;

import com.buli.blmall.generator.config.DataSourceConfig;
import com.buli.blmall.generator.convert.JdbcTypeConvert;
import com.buli.blmall.generator.enums.DbColumnType;
import com.buli.blmall.generator.enums.JdbcType;
import org.apache.commons.lang3.StringUtils;

import java.sql.*;
import java.util.*;

/**
 * @author xiang.gao
 * @date 2024/12/5 17:13
 */
public class MetaWrapper {

    private final Connection connection;
    public static MetaWrapper init(DataSourceConfig config) {
        try {
            return new MetaWrapper(config.getUrl(), config.getUsername(), config.getPassword());
        } catch (RuntimeException e) {
            throw new RuntimeException("加载驱动失败", e);
        }
    }

    private List<MetaTable.Column> getColumns(String schema, String tableName) throws SQLException {
        List<MetaTable.Column> columnList = new ArrayList<>();

        Set<String> primaryKeys = new HashSet();
        DatabaseMetaData databaseMetaData = connection.getMetaData();
        try {
            // 表主键
            ResultSet primaryKeysResultSet = databaseMetaData.getPrimaryKeys(connection.getCatalog(), schema, tableName);
            try {
                while(primaryKeysResultSet.next()) {
                    primaryKeys.add(primaryKeysResultSet.getString("COLUMN_NAME"));
                }
            } catch (Throwable throwable) {
                throw throwable;
            } finally {
                if (primaryKeysResultSet != null) {
                    primaryKeysResultSet.close();
                }
            }
        } catch (SQLException var17) {
            throw new RuntimeException("读取表主键信息:" + tableName + "错误:", var17);
        }

        ResultSet columnResultSet = null;
        try{
            //表字段信息
            columnResultSet = databaseMetaData.getColumns(connection.getCatalog(), schema, tableName, "%");
            while (columnResultSet.next()) {
                //遍历表字段所有元数据
                /*for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
                    System.out.println(resultSet.getMetaData().getColumnName(i + 1) + ":" + resultSet.getString(i + 1));
                }*/
                MetaTable.Column column = new MetaTable.Column();
                column.setName(columnResultSet.getString("COLUMN_NAME"));
                column.setTypeName(columnResultSet.getString("TYPE_NAME"));
                column.setJdbcType(JdbcType.forCode(columnResultSet.getInt("DATA_TYPE")));
                column.setDefaultValue(columnResultSet.getString("COLUMN_DEF"));
                column.setRemarks(columnResultSet.getString("REMARKS"));
                column.setLength(columnResultSet.getInt("COLUMN_SIZE"));
                column.setScale(columnResultSet.getInt("DECIMAL_DIGITS"));
                column.setAutoIncrement(columnResultSet.getString("IS_AUTOINCREMENT").equalsIgnoreCase("YES"));
                column.setPrimaryKey(primaryKeys.contains(column.getName()));
                column.setJavaType(JdbcTypeConvert.getColumnType(column, DbColumnType.OBJECT).getType());
                column.setJavaField(columnResultSet.getString("COLUMN_NAME"));
                columnList.add(column);
            }
            return columnList;
        } catch (Exception e) {
            throw new RuntimeException("读取数据库表信息出现错误", e);
        } finally {
            if (columnResultSet != null) {
                try {
                    columnResultSet.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    public MetaTable.Table getTable(String schema, String tableName) {
        ResultSet resultSet = null;
        try {
            DatabaseMetaData metaData = connection.getMetaData();
            resultSet = metaData.getTables(connection.getCatalog(), schema, tableName, new String[]{"table"});
            if (!resultSet.next()) {
                throw new RuntimeException("表不存在");
            }
            /*for (int i = 0; i < resultSet.getMetaData().getColumnCount(); i++) {
                System.out.println(resultSet.getMetaData().getColumnName(i + 1) + ":" + resultSet.getString(i + 1));
            }*/
            MetaTable.Table table = new MetaTable.Table();
            table.setName(resultSet.getString("TABLE_NAME"));
            table.setRemarks(formatComment(resultSet.getString("REMARKS")));
            table.setTableType(resultSet.getString("TABLE_TYPE"));
            table.setColumnList(getColumns(schema, table.getName()));
            System.out.println("读取数据库表元信息...");
            return table;
        } catch (SQLException var11) {
            throw new RuntimeException("读取数据库表信息出现错误", var11);
        }  finally {
            if (resultSet != null) {
                try {
                    resultSet.close();
                } catch (SQLException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }



    private MetaWrapper(String url, String username, String password) {
        try {
            Class.forName("com.mysql.cj.jdbc.Driver");
            connection = DriverManager.getConnection(url, username, password);
            System.out.println("数据库链接成功...");
        } catch (Exception e) {
            throw new RuntimeException("数据库连接错误:" + e);
        }
    }


    public void closeConnection() {
        Optional.ofNullable(this.connection).ifPresent((con) -> {
            try {
                con.close();
                System.out.println("关闭数据库链接...");
            } catch (SQLException var2) {
                var2.printStackTrace();
            }
        });
    }

    public String formatComment(String comment) {
        return StringUtils.isBlank(comment) ? "" : comment.replaceAll("\r\n", "\t");
    }

}
